#include "aerial\Game\GameScene\MainMenuScene.h"

#include "aerial\Game\GameScene\RoomScene.h"

#include "aerial\Object\Text.h"
#include "aerial\Object\Button.h"
#include "aerial\Object\Panel.h"
#include "aerial\Object\TextInput.h"

#include "aerial\Scene\Event.h"
#include "aerial\Core\Core.h"

//#include "

bool MainMenuScene::initialize()
{
	menu = new Panel(hgeResMan, -250.f, 0, 250.f, 600.f);
	enterIP = new Panel(hgeResMan, 200.f, -200.f, 560.f, 200.f);
	enterUserName = new Panel(hgeResMan, 200.f, -200.f, 560.f, 150.f);

	enterUserName->placeGuiObjectOffset(
		usrName2 = new TextInput(hgeResMan, 240.f, 30.f),
		100.f, 60.f);
	enterUserName->placeGuiObjectOffset(
		hint2 = new Text(hgeResMan, 400.f, 30.f),
		100.f, 20.f);
	enterUserName->placeGuiObjectOffset(
		nameLabel2 = new Text(hgeResMan, 40.f, 30.f),
		20.f, 60.f);
	hint2->SetText("Input User Name");
	nameLabel2->SetText("name");
	enterUserName->placeGuiObjectOffset(
		create = new Button(hgeResMan, 0.f, "Create",
			new SEvent<MainMenuScene>(this, &MainMenuScene::Create)
		), 
		300.f, 100.f);
	enterUserName->placeGuiObjectOffset(
		create = new Button(hgeResMan, 0.f, "Cancel",
			new SEvent<MainMenuScene>(this, &MainMenuScene::CancelCreate)
		), 
		400.f, 100.f);

	enterIP->placeGuiObjectOffset(
		usrName = new TextInput(hgeResMan, 240.f, 30.f),
		100.f, 60.f);
	enterIP->placeGuiObjectOffset(
		IPAddress = new TextInput(hgeResMan, 400.f, 30.f), 
		100.f, 100.f);
	enterIP->placeGuiObjectOffset(
		cancelJoin = new Button(hgeResMan, 0.f, "Cancel",
			new SEvent<MainMenuScene>(this, &MainMenuScene::CancelJoinRoom)
		), 
		400.f, 150.f);
	enterIP->placeGuiObjectOffset(
		connectGame = new Button(hgeResMan, 0.f, "Connect",
			new SEvent<MainMenuScene>(this, &MainMenuScene::ConnectRoom)
		), 
		300.f, 150.f);

	enterIP->placeGuiObjectOffset(
		hint = new Text(hgeResMan, 400.f, 30.f),
		100.f, 20.f);
	enterIP->placeGuiObjectOffset(
		nameLabel = new Text(hgeResMan, 40.f, 30.f),
		20.f, 60.f);
	enterIP->placeGuiObjectOffset(
		IPLabel = new Text(hgeResMan, 40.f, 30.f),
		20.f, 100.f);
	
	hint->SetText("Enter IP Address to connect to Room");
	nameLabel->SetText("Name");
	IPLabel->SetText("IP");

	menu->SetTransfromationTween(0.f, 0.f, 0.25f);
	menu->placeGuiObjectOffset(
		createGame = new Button(hgeResMan, 0.2f, "Create Game",
			new SEvent<MainMenuScene>(this, &MainMenuScene::CreateRoom)
		), 
		40.0f, 120.0f);
	menu->placeGuiObjectOffset(
		joinGame = new Button(hgeResMan, 0.2f, "Join Game",
			new SEvent<MainMenuScene>(this, &MainMenuScene::JoinRoom)
		), 
		40.0f, 170.0f);
	menu->placeGuiObjectOffset(
		exitGame = new Button(hgeResMan, 0.2f, "Exit", 
			new SEvent<MainMenuScene>(this, &MainMenuScene::Exit)
		),
		40.0f, 270.0f);

	menu->addToGui(sceneManager);
	enterIP->addToGui(sceneManager);
	enterUserName->addToGui(sceneManager);
	return true;
}

void MainMenuScene::Leave()
{
	menu->SetTransfromationTween(-250.f, 0.f, 0.25f, 
		new SEvent<MainMenuScene>(this, &MainMenuScene::leaveCounter));
}

void MainMenuScene::CreateRoom()
{
	if (!createRoom)
	{
		createRoom = true;
		enterUserName->SetTransfromationTween(200.f, 150.f, 0.25f);
		joinGame->bEnabled = false;
		createGame->bEnabled = false;
		exitGame->bEnabled = false;
	}
}

void MainMenuScene::Create()
{
	if (!strlen(usrName2->GetText()))
	{
		hint2->SetText("Name cannot be empty.");
		return;
	}
	if (netIO->StartBattleServer())
	{
		netIO->SetBattleServer(true);
		sceneManager->setNextScene(new RoomScene(usrName2->GetText()));
		Leave();
	}
}

void MainMenuScene::CancelCreate()
{
	if (createRoom)
	{
		usrName2->SetText("");
		enterUserName->SetTransfromationTween(200.f,  -200.f, 0.25f);
		joinGame->bEnabled = true;
		createGame->bEnabled = true;
		exitGame->bEnabled = true;
		usrName2->bEnabled = true;
		createRoom = false;
	}
}

void MainMenuScene::JoinRoom()
{
	if (!joinRoom)
	{
		joinRoom = true;
		hint->SetText("Enter IP Address to connect to Room");
		enterIP->SetTransfromationTween(200.f, 150.f, 0.25f);
		joinGame->bEnabled = false;
		createGame->bEnabled = false;
		exitGame->bEnabled = false;
	}
}

void MainMenuScene::Exit()
{
	netIO->CloseConnection();
	Leave();
}

void MainMenuScene::ConnectRoom()
{
	if (joinRoom && !connectRoom)
	{
		const char* ip = IPAddress->GetText();
		if (!strlen(usrName->GetText()))
		{
			hint->SetText("Name cannot be empty.");
			return;
		}
		if (!NetIO::IsValidIP(ip))
		{
			hint->SetText("Illegal IP Format.");
			return;
		}
		SystemAddress sa;
		if (sa.FromStringExplicitPort(ip, BATTLE_SERVER_PORT, 4)) 
		{
			onceConnected = true;
			netIO->SetBattleServer(false);
			connectRoom = true;
			IPAddress->bEnabled = false;
			usrName->bEnabled = false;
			hint->SetText("Connecting...");
			netIO->ConnectToBattleServer(ip);
		}
		else {
			hint->SetText("Illegal IP Address.");
		}
	}
}

void MainMenuScene::CancelJoinRoom()
{
	if (joinRoom)
	{
		if ( connectRoom )
		{
			connectRoom = false;
			netIO->node->CancelConnectionAttempt(UNASSIGNED_SYSTEM_ADDRESS);
			IPAddress->bEnabled = true;
		}
		if ( onceConnected )
		{
			onceConnected = false;
			netIO->node->Shutdown(0);
		}
		IPAddress->SetText("");
		joinRoom = false;
		enterIP->SetTransfromationTween(200.f,  -200.f, 0.25f);
		joinGame->bEnabled = true;
		createGame->bEnabled = true;
		exitGame->bEnabled = true;
		IPAddress->bEnabled = true;
		usrName->bEnabled = true;
	}
}

bool MainMenuScene::update(float dt)
{
	if (connectRoom) {
		Packet* p;
		BitStream bso;
		Join iJoin;
		bool needToCloseConnection = false;
		if (p = netIO->m_recv())
		{
			switch (p->data[0])
			{
			case ID_CONNECTION_REQUEST_ACCEPTED:
				cout << "accepted.\n";
				iJoin.userName = usrName->GetText();
				iJoin.Serialize(&bso);
				netIO->RegisterServerAddress(&p->systemAddress);
				netIO->sendToBattleServer(&bso);
				break;
			case ID_JOIN_ACK:
				{
					uchar id, whead;
					BitStream bsi(p->data, p->length, false);
					bsi.Read(whead);
					bsi.Read(id);
					netIO->SetMeId(id);
					cout << (int)id << " assigned.\n";
					sceneManager->setNextScene(new RoomScene(usrName->GetText()));
					Leave();
				}
				break;
			case ID_NAME_DUPLICATE:
				connectRoom = false;
				needToCloseConnection = true;
				IPAddress->bEnabled = true;
				usrName->bEnabled = true;
				hint->SetText("Name duplicate. Change a name.");
				break;
			case ID_CONNECTION_ATTEMPT_FAILED:
				needToCloseConnection = true;
				connectRoom = false;
				hint->SetText("Remote Server Not Found 404 :(");
				IPAddress->bEnabled = true;
				usrName->bEnabled = true;
				break;
			case ID_DISCONNECTION_NOTIFICATION:
				needToCloseConnection = true;
				connectRoom = false;
				hint->SetText("Refused. Game Started or Room Full.");
				IPAddress->bEnabled = true;
				usrName->bEnabled = true;
				break;
			case ID_ALREADY_LOCK:
				needToCloseConnection = true;
				connectRoom = false;
				hint->SetText("Game started on remote server");
				IPAddress->bEnabled = true;
				usrName->bEnabled = true;
				break;
			case ID_FULL:
				needToCloseConnection = true;
				connectRoom = false;
				hint->SetText("Room full on remote server");
				IPAddress->bEnabled = true;
				usrName->bEnabled = true;
				break;
			case ID_CONNECTION_LOST:
				cout << "connection lost from remote server.\n";
				break;
			default:
				cout << "cannot handle packet with head " << (int)p->data[0] << endl;
			}
			netIO->m_Deallocate(p);
			if (needToCloseConnection)
			{
				netIO->CloseConnection();
			}
		}
	}
	return false;
}

bool MainMenuScene::render(float dt)
{
	hge->Gfx_Clear(0xffffffff);
	acc->Render();
	gui->Render();
	return false;
}


void MainMenuScene::Enter() 
{
	gui->Enter();
}
